﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.Ports;
using System.Threading;

namespace LED_Tester
{
    public class ClassLuxBoard
    {
        private SerialPort sptLuxBoard = new SerialPort();

        private int result = -1;

        private int luxRange = 0;

        public double luxValue;

        public SerialPort SptLuxBoard
        {
            get { return sptLuxBoard; }
            set { sptLuxBoard = value; }
        }

        public int Join(string portName)
        {
            int ret = -1;

            sptLuxBoard.BaudRate = 961200;
            sptLuxBoard.DataBits = 8;
            sptLuxBoard.Parity = Parity.None;
            sptLuxBoard.StopBits = StopBits.One;

            sptLuxBoard.WriteTimeout = 300;
            sptLuxBoard.ReceivedBytesThreshold = 3;
            sptLuxBoard.DtrEnable = true;
            sptLuxBoard.RtsEnable = false;

            sptLuxBoard.DataReceived += new SerialDataReceivedEventHandler(LuxBoard_DataReceived);

            if (sptLuxBoard.IsOpen)
            {
                sptLuxBoard.Close();
            }

            try
            {
                sptLuxBoard.PortName = portName;
                sptLuxBoard.Open();
                sptLuxBoard.DtrEnable = false;
                sptLuxBoard.RtsEnable = true;
            }
            catch { }

            if (sptLuxBoard.IsOpen)
            {
                byte[] command = new byte[] { 0x82, 0x01, 0xFE };

                int count = 0;

                while (count < 10)
                {
                    sptLuxBoard.Write(command, 0, 3);
                    Thread.Sleep(400);

                    if (result == 0)
                    {
                        ret = 0;
                        break;
                    }
                    else
                    {
                        ret = 1;
                        count++;
                    }
                }
            }
            else
            {
                ret = 1;
            }

            return ret;
        }

        public void Measure(double luxDarkValue, double distance, ref double luxStanValue)
        {
            if (sptLuxBoard.IsOpen && result == 0)
            {
                luxRange = 0;
                byte[] command = new byte[] { 0x82, 0x01, 0xFD };
                sptLuxBoard.Write(command, 0, 3);
                Thread.Sleep(20);
                sptLuxBoard.Write(command, 0, 3);
                luxStanValue = (luxValue - luxDarkValue) * Math.Pow(distance, 2d);
            }
            else
            {
                luxStanValue = 0;
            }
        }

        public void Dark(ref double luxDarkValue)
        {
            if (sptLuxBoard.IsOpen && result == 0)
            {
                luxRange = 0;
                byte[] command = new byte[] { 0x82, 0x01, 0xFE };
                sptLuxBoard.Write(command, 0, 3);
                Thread.Sleep(20);
                sptLuxBoard.Write(command, 0, 3);
                luxDarkValue = luxValue;
            }
            else
            {
                luxDarkValue = 0;
            }
        }

        public void Exit()
        {
            if (sptLuxBoard.IsOpen && result == 0)
            {
                sptLuxBoard.Close();
            }
        }

        public double CalcHalfWidth(double[] luxData, double gammaSample)
        {
            double halfWidth = -1;

            double min = luxData.Min();

            for (int i = 0; i < luxData.Length; i++)
            {
                luxData[i] -= min;
            }

            double max = luxData.Max();

            double halfMax = max / 2;

            int maxIndex = Array.IndexOf(luxData, max);

            int j = maxIndex, k = maxIndex;

            while (j >= 0)
            {
                if (luxData[j] <= halfMax)
                {
                    break;
                }
                j--;
            }
            while (k <= luxData.Length - 1)
            {
                if (luxData[k] <= halfMax)
                {
                    break;
                }
                k++;
            }

            if ((j == 0 && luxData[j] > halfMax) || (k == luxData.Length - 1 && luxData[k] > halfMax))
            {
                halfWidth = 0;
            }
            else
            {
                double lo = (halfWidth - luxData[j]) / (luxData[j + 1] - luxData[j]) + j;
                double hi = (halfWidth - luxData[k]) / (luxData[k - 1] - luxData[k]) + k;

                halfWidth = (hi - lo) * gammaSample;
            }

            return halfWidth;
        }

        private void LuxBoard_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            byte[] data = new byte[3];

            int count = 0;

            while (sptLuxBoard.BytesToRead < 3)
            {
                if (count == 100)
                {
                    break;
                }

                Thread.Sleep(2);

                count++;
            }

            if (count == 100 && sptLuxBoard.BytesToRead < 3)
            {
                result = 1;
                return;
            }
            else
            {
                try
                {
                    sptLuxBoard.Read(data, 0, 3);
                }
                catch { }

                if (data[1] > 0xC0)
                {
                    if (luxRange == 0)
                    {
                        byte[] command = new byte[] { 0x82, 0x02, 0xFD };

                        sptLuxBoard.Write(command, 0, 3);
                        luxRange = 1;
                    }
                    else if (luxRange == 1)
                    {
                        byte[] command = new byte[] { 0x82, 0x03, 0xFC };

                        sptLuxBoard.Write(command, 0, 3);
                        luxRange = 2;
                    }
                    else
                    {
                        return;
                    }
                }

                byte[] temp = new byte[2];

                temp[0] = data[2];
                temp[1] = data[1];

                int value = BitConverter.ToInt16(temp, 0);

                if (luxRange == 0)
                {
                    luxValue = (double)value;
                }
                else if (luxRange ==1)
                {
                    luxValue = (double)(value * 10);
                }
                else if (luxRange == 2)
                {
                    luxValue = (double)(value * 100);
                }

                sptLuxBoard.DiscardInBuffer();

                result = 0;
            }
        }
    }
}
